#!/usr/bin/env python

import os,sys,time,string
import thread,shutil,glob
import traceback

#from inspect import currentframe
#print currentframe().f_lineno
#print currentframe().f_code.co_name
#print currentframe().f_code.co_filename

__version__ = '1.0.3'
__lastmodifytime__ = '2009-5-11'

CRITICAL = 50 
ERROR = 40 
WARNING = 30 
INFO = 20 
DEBUG = 10 
NOTSET = 0

mutex_lock = thread.allocate_lock()

class FCLog:
    def __init__(self, file, unMask = NOTSET, maxsize = 1024*1024*100, backupnum = 10):
        """
        init func
        @param file: log file name
        @param umMask: log priority
        @param maxsize: log file max size
        @param backupnum: max back up log file num
        """
        self.filename = file
        self.maxsize = maxsize
        self.backupnum = backupnum
        self.unMask = unMask
        self.show = True
        
    def SetShowEnable(self, flag):
        """
        set show flag(print or not print log message)
        @param flag: Ture or Flase 
        """
        self.show = flag
        
    def SetFileNum(self, num):
        """
        set back up file num
        @param num: backup log file num
        """
        self.backupnum = num
        
    def SetLogFile(self, file):
        """
        set log file name
        @param file: file name
        """
        self.filename = file
        
    def SetLogPriority(self, priority):
        """
        set priority
        @param priority: low than priority can not writed
        """
        self.unMask = priority        
    
    def SetLogMaxSize(self, maxsize):
        """
        set log max size
        @param maxsize: log max size
        """
        self.maxsize = maxsize
        
    def GetFileName(self):
        """
        get backup file name        
        """
        strtime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        filename = self.filename + '_' + strtime
        return filename
    
    def CheckLogSize(self):
        """
        check log file size
        """
        if not os.path.exists(self.filename):
            return
        size = os.path.getsize(self.filename)
        if size >= self.maxsize:
            shutil.move(self.filename, self.GetFileName())
            
    def CheckFileNum(self):
        """
        check backup log file num, if more than backupnum then remove the first backup file
        """
        path = os.path.dirname(self.filename)
        profile = os.path.basename(self.filename)        
        files = glob.glob1(path, profile + '_*')
        if len(files) <= self.backupnum:
            return
        delfile = files[0]
        for file in files:
            if file < delfile:
                delfile = file
        delfullfile = os.path.join(path, delfile)
        os.remove(delfullfile)
        
    def GetPriorityStr(self, npriority):
        """
        get str priority
        @param npriority: conv from int to str
        """
        str = 'NOTSET'
        if npriority == DEBUG:
            str = 'DEBUG'
        elif npriority == INFO:
            str = 'INFO'
        elif npriority == WARNING:
            str = 'WARNING'
        elif npriority == ERROR:
            str = 'ERROR'
        elif npriority == CRITICAL:
            str = 'CRITICAL'
        return str
    
    def LogMsg(self, npriority, msg):
        """
        write msg
        @param npriority: msg priority
        @param msg: write content
        """
        mutex_lock.acquire()
        try:
            self.CheckLogSize()
            self.CheckFileNum()            
        except Exception, msg:
            print msg
        except :
            print "clean backup log error"
        try:
            log = open(self.filename, "a")
            strTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())            
            LogString = self.GetPriorityStr(npriority) + "[" + strTime + "]: " + msg + '\n'
            if npriority >= self.unMask:
                log.write(LogString)
            log.close()
            if self.show:
                print LogString        
        except:
            print "Write Msg %s Error: " % str(msg)
            log.close()
        mutex_lock.release()
    
    def notset(self, msg):
        self.LogMsg(NOTSET, msg)
        
    def debug(self, msg):
        self.LogMsg(DEBUG, msg)
        
    def info(self, msg):
        self.LogMsg(INFO, msg)
        
    def warning(self, msg):
        self.LogMsg(WARNING, msg)
        
    def error(self, msg):
        self.LogMsg(ERROR, msg)
        
    def critical(self, msg):
        self.LogMsg(CRITICAL, msg)
        
    def log_traceback(self):
        """
        log exception traceback to logger
        a little different from log.exception
        """
        ei = sys.exc_info()
        lines = traceback.format_exception(ei[0], ei[1], ei[2])
        for line in lines[:-1]:
            elines = line.splitlines()
            for eline in elines:                
                self.error(eline.rstrip())
                self.error(lines[-1])


def log_traceback(logger):
    """
    log exception traceback to logger
    a little different from log.exception
    """
    ei = sys.exc_info()
    lines = traceback.format_exception(ei[0], ei[1], ei[2])
    for line in lines[:-1]:
        elines = line.splitlines()
        for eline in elines:
            logger.error(eline.rstrip())
    logger.error(lines[-1])        
        
        
if __name__ == "__main__":
    testlog = FCLog('D:\\test.log')
    testlog.SetLogMaxSize(10 * 1024)
    testlog.SetFileNum(2)   
    
    testlog.info("who am i")
    testlog.notset("who am i")
    testlog.debug("who am i")
    testlog.warning("who am i")
    testlog.error("who am i")
    testlog.critical("who am i")
    
    
    testlog.SetLogPriority(ERROR)
    testlog.error("who am i")
    testlog.info("who am i")
    
    try:
        print 100/0
    except:
        testlog.log_traceback()
            
        
        
    